﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using Public;
using System.IO;
using System.Diagnostics;
using System.Security.Cryptography;

namespace ControlCenterTarget
{
    // NOTE: If you change the class name "Service1" here, you must also update the reference to "Service1" in App.config.
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single,IncludeExceptionDetailInFaults=true)]
    public class Service : IService
    {
        private List<Process> processes;

        public Service()
        {
            this.processes = new List<Process>();
        }

        #region IService Members

        string IService.GetMachineName()
        {
            return System.Environment.MachineName;
        }

        void IService.SendFile(FileWrapper fileWrapper)
        {
            try
            {
                var sourceStream = fileWrapper.FileStream;
                if (File.Exists(fileWrapper.FilePath))
                    File.SetAttributes(fileWrapper.FilePath, FileAttributes.Normal);
                FileStream targetStream = new FileStream(fileWrapper.FilePath, FileMode.Create, FileAccess.Write, FileShare.None);
                Byte[] buffer = new byte[4096];
                int count = 0;
                while ((count = sourceStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    targetStream.Write(buffer, 0, count);
                }
                targetStream.Close();
                sourceStream.Close();
            }
            catch
            {
            }
        }

        bool IService.CheckFile(string path, string md5)
        {
            try
            {
                if (!File.Exists(path))
                    return false;
                FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
                byte[] data = MD5.Create().ComputeHash(fileStream);
                StringBuilder stringBuilder = new StringBuilder();
                for (int i = 0; i < data.Length; i++)
                    stringBuilder.Append(data[i].ToString("x2"));
                fileStream.Close();
                if (md5 == stringBuilder.ToString())
                    return true;
                else
                    return false;
            }
            catch
            {
                return false;
            }
        }

        Result IService.RunProgram(string path, string arguments)
        {
            if (File.Exists(path))
            {
                try
                {
                    if (arguments == null || arguments == "")
                    {
                        ProcessStartInfo info = new ProcessStartInfo(path);
                        info.UseShellExecute = false;
                        Process process = Process.Start(info);
                        this.processes.Add(process);
                    }
                    else
                    {
                        ProcessStartInfo info = new ProcessStartInfo(path, arguments);
                        info.UseShellExecute = false;
                        Process process = Process.Start(info);
                        this.processes.Add(process);
                    }
                    return new Result("The program has been started successfully.");
                }
                catch (Exception e)
                {
                    return new Result("Exception is thrown during running a program.", e);
                }
            }
            else
                return new Result("File does not exist.", new List<Exception>());
        }

        Result IService.RunTerminalScript(List<string> scriptLines)
        {
            try
            {
                ProcessStartInfo info = new ProcessStartInfo("cmd.exe");
                info.CreateNoWindow = true;
                info.RedirectStandardError = true;
                info.RedirectStandardInput = true;
                info.RedirectStandardOutput = true;
                info.UseShellExecute = false;
                Process CMDProcess = Process.Start(info);
                foreach (string line in scriptLines)
                    CMDProcess.StandardInput.WriteLine(line);
                CMDProcess.StandardInput.WriteLine("exit");
                string lineReader = "", outputString = "";
                while (!CMDProcess.StandardOutput.EndOfStream)
                {
                    outputString += lineReader + System.Environment.NewLine;
                    lineReader = CMDProcess.StandardOutput.ReadLine();
                }
                return new Result(outputString);
            }
            catch(Exception e)
            {
                return new Result("Exception is thrown during running terminal script.", e);
            }
        }

        void IService.KillAllControlledPrograms()
        {

            foreach (Process p in this.processes)
                if (p != null)
                    try
                    {
                        p.Kill();
                    }
                    catch { }
        }
        #endregion
    }
}
